#!/bin/sh
# $Id: options.sh 30 2009-08-02 22:47:14Z lordylordy $
VERSION=20090203-1

HOME=$( echo $0 | sed -r 's|[^/]+$||' )
HOME=$(cd "${HOME:-.}" ; pwd )

#echo "HOME=$HOME"

#$1 = file
#$2 = variable
#$3=value
OPTION_SET() {
    q='"'
    if grep -q "^$2=" $1 ; then
        cp "$1" "$1.old"
        sed "s^$2=.*$2=$q$3$q" "$1.old" > "$1"
    else
        echo "$2=$q$3$q" >> "$1"
    fi
}

# $1=help file format <option name:help text|choice1|..|choicen>
# $2=cfg file  format <option name=value>
OPTION_GET() {
    OPTION_PARSE MODE=GET "$@"
}


# $1=help file format <option name:help text|choice1|..|choicen>
# $2=cfg file  format <option name=value>
OPTION_TABLE() {
    OPTION_PARSE MODE=TABLE "$@"
}

OPTION_PARSE() {
    awk '
ARGIND==2 { addVal($0,":",help,1); next; }
ARGIND==3 { addVal($0,"=",val,0); next; }

function addVal(line,sep,arr,addToOrder,   i,name,rest) {

    sub(/\r$/,"",line);
    i = index(line,sep);
    if (i > 0 ) {
        name=trim(substr(line,1,i-1));
        rest=trim(substr(line,i+1));
        if (addToOrder && !(name in help)) {
            order = order "|" name ;
        }
        arr[name] = rest;
    }
}
function trim(x) {
    sub(/^[ "'"'"']+/,"",x);
    sub(/[ "'"'"']+$/,"",x);
    return x;
}
function html_table(    i,n,current,sel,opts,optCount) {
    i=1;
    print "<table class=options>";
    print "<tr class=optionrow><td>Option</td><td>Value</td><td>Description</td></tr>";

    split(substr(order,2),ord,"|");

    for(i=1 ; ord[i] != "" ; i++) {

        n=ord[i];

        current=(n in val)?val[n]:""

        draw_choice="";
        if (n in options) {

            split(options[n],opts,"|");
            optCount=0;
            for(o in opts) optCount++;

            if (optCount > 0 && !(n in val) ) {
                #Take default from first option
                current = val[n]=opts[1];
            }
            if (optCount > 1) {
                draw_choice = sprintf("<td class=optionval><select name=option_%s>",n);
                for(o=1 ; o <= optCount ; o++) {
                    if (opts[o] == current) {
                        sel=" selected=\"selected\"";
                    } else {
                        sel="";
                    }
                    draw_choice = draw_choice sprintf("\t<option value=\"%s\" %s>%s</option>\n",opts[o],sel,opts[o]);
                }
                draw_choice = draw_choice "</select></td>";
            }

        }
        if (draw_choice == "") {
            draw_choice = sprintf("<td class=optionval><input type=text name=option_%s value=\"%s\" ></td>",n,current);
        }

        printf "<tr class=optionrow"(i%2)"><td class=optionname><b>"n"</b> (%s)",(n in val)?val[n]:"unset";
        print "<input type=hidden name=orig_option_"n" value=\""val[n]"\" ></td>";
        print draw_choice;
        print "<td class=optionhelp>"help[n]"</td></tr>";
    }
    print "</table>";
}

#Return file name with shell meta-chars escaped.
function quoteFile(f,
    j,ch) {
    if (index(f,"\"") == 0) {
        return "\""f"\"";
    } else if (index(f,"'"'"'") == 0) {
        return "'"'"'"f"'"'"'";
    } else {
        meta=" !&[]*()\"'"'"'";
        for(j= 1 ; j <= length(meta) ; j++ ) {
            ch=substr(meta,j,1);
            if (index(f,ch)) {
                #DEBUG("Escaping ["ch"] from "f);
                gsub("["ch"]","\\"ch,f);
                #DEBUG("= "f);
                }
        }
        return f;
    }
}

function shell_assign() {
    for (n in help) {
        if (n in val) {
            v=val[n];
        } else {
            split(options[n],opts,"|");
            v=opts[1];
        }
        printf "option_%s=%s;",n,quoteFile(v);
    }
    #Also do additional options in the cfg but not in the help
    for (n in val) {
        if(!(n in help)) {
            printf "option_%s=%s;",n,quoteFile(val[n]);
        }
    }
}

END {
    for (n in help) {
        i=index(help[n],"|");
        if (i > 0 ) {
            options[n]=substr(help[n],i+1);
            help[n]=substr(help[n],1,i-1);

        }
    }
    if (index(MODE,"TABLE")) {
        html_table();
    } else if (MODE == "GET") {
        shell_assign();
    } else {
        print "ERROR";
    }
}
' "$@"
}

func="$1"
shift
case "$func" in
    TABLE) OPTION_TABLE "$@" ;;
    GET) OPTION_GET "$@" ;;
    SET) OPTION_SET "$@" ;;
    *) cat <<HERE
$0 TABLE helpFile configFile
    Draw html table to set options.
    help file format <option name:help text|choice1|..|choicen>
    cfg file  format <option name=value>

$0 GET helpFile configFile
    Disply a line of all settings. This can be passed to eval eg.
    eval \`$0 GET helpfile configfile\`
    Note options that are not set in cfg take first value in help as thier default values

$0 SET configFile name value
HERE
    ;;
esac

#OPTION_TABLE test_option.cfg.help test_option.cfg
#OPTION_SET test_option.cfg free slave2
#OPTION_SET test_option.cfg slave prisoner

# vi:shiftwidth=4:tabstop=4:expandtab
